﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Lilium.ComponentModel;
using System.Windows.Forms;
using System.Diagnostics;

namespace Lilium.UI.Forms
{
	public sealed class TextBoxExtension : BasicExtension<TextBox>
	{
		#region public bool EnableAutocomplete

		private bool m_EnableAutocomplete;

		public bool EnableAutocomplete
		{
			[DebuggerNonUserCodeAttribute]
			get
			{
				return m_EnableAutocomplete;
			}
			[DebuggerNonUserCodeAttribute]
			set
			{
				if (EnableAutocomplete != value)
				{
					m_EnableAutocomplete = value;
					if (!value)
					{
						PreviouslyTypedTextLength = 0;
					}
				}
			}
		}

		#endregion

		#region CompletionListNeeded event

		public event EventHandler<CompletionListNeededEventArgs> CompletionListNeeded;

		private void OnCompletionListNeeded(CompletionListNeededEventArgs e)
		{
			if (e == null) throw new ArgumentNullException("e");

			var handler = CompletionListNeeded;
			if (handler != null)
				handler(this, e);
			if (e.CompletionList == null)
				e.CompletionList = Enumerable.Empty<object>();
		}

		#endregion

		protected override void OnAttach()
		{
			Owner.TextChanged += Owner_TextChanged;
		}

		protected override void OnDetach()
		{
			Owner.TextChanged += Owner_TextChanged;
		}

		private void HandleAutocomplete()
		{
			if (string.IsNullOrEmpty(Owner.Text))
			{
				PreviouslyTypedTextLength = 0;
				return;
			}
			
			var cursorPosition =
				Owner.SelectionStart < Owner.Text.Length
				? Owner.SelectionStart
				: Owner.Text.Length;

			var typedText = Owner.Text.Substring(0, cursorPosition);

			if (!string.IsNullOrEmpty(typedText) && (typedText.Length > PreviouslyTypedTextLength))
			{
				var completionListNeededEventArgs = new CompletionListNeededEventArgs(typedText, 1);
				OnCompletionListNeeded(completionListNeededEventArgs);
				var matchingItem = completionListNeededEventArgs.CompletionList.FirstOrDefault();
				if (matchingItem != null)
				{
					var text = string.Format("{0}", matchingItem);
					Owner.Text = text;
					Owner.Select(cursorPosition, text.Length - cursorPosition);
				}
			}

			PreviouslyTypedTextLength = typedText.Length;
		}

		#region Event Handlers

		private void Owner_TextChanged(object sender, EventArgs e)
		{
			if (EnableAutocomplete)
				HandleAutocomplete();
		}

		#endregion

		#region private int PreviouslyTypedTextLength

		private int m_PreviouslyTypedTextLength;

		private int PreviouslyTypedTextLength
		{
			[DebuggerNonUserCodeAttribute]
			get
			{
				return m_PreviouslyTypedTextLength;
			}
			[DebuggerNonUserCodeAttribute]
			set
			{
				m_PreviouslyTypedTextLength = value;
			}
		}

		#endregion
	}
}
